


/**
 * primitive Wall 大量加载
 * 
 */
import Primitive from "../Primitive"

const DEFAULT_STYLE = {
  minRadius: 10,
  minHeight: 30,
  color: Cesium.Color.GOLD,
  slices: 128,
  speed: 10
}

export default class DiffuseWallPrimitive extends Primitive {
  /**
   * 
   * @param {*} center 
   * @param {*} radius 
   * @param {*} height 
   */
  constructor(center, radius, height) {
    super()
    this._center = center
    this._height = height
    this._radius = radius
    this._currentHeight = height || 0
    this._currentRadius = 10
    this._style = { ...DEFAULT_STYLE }
    this._type = 'diffuseWall_primitive'

    this.mounted()
    this.startRotate()
  }

  /**
   * 不断更新
   */
  startRotate() {
    this._timer = setInterval(() => {
      if (!this._layer) return

      this.delegate = this.delegate && this.delegate.destroy()
      this._currentRadius += this._radius / this._style.speed / 100
      this._currentHeight -= this._height / this._style.speed / 100
      if (
        this._currentRadius > this._radius ||
        this._currentHeight < this._style.minHeight
      ) {
        this._currentRadius = this._style.minRadius
        this._currentHeight = this._height
      }

      let positions = this._getPositions(this._radius)

      let geometry = new Cesium.WallGeometry({
        positions: positions,
        minimumHeights: this._getHeights(positions.length, 0),
        maximumHeights: this._getHeights(positions.length, this._currentHeight)
      })

      this.delegate = new Cesium.Primitive({
        geometryInstances: new Cesium.GeometryInstance({
          geometry: geometry
        }),
        appearance: new Cesium.MaterialAppearance({
          material: Cesium.Material.fromType('DiffuseWall', {
            color: this._style?.color
          }),
          flat: true
        }),
        asynchronous: false
      })
      this._layer.collection.add(this.delegate)
    }, 1000 / 60);
  }

  /**
   * 销毁定时器
   */
  destroy() {
    this.timer = null
    this.delegate && this.delegate.destroy()
  }

  /**
   * 初始化
   */
  mounted() {
    this.positions = this._positions
    this.style = this._style
    let positions = this._getPositions(this._radius)

    let geometry = new Cesium.WallGeometry({
      positions: positions,
      minimumHeights: this._getHeights(positions.length, 0),
      maximumHeights: this._getHeights(positions.length, this._currentHeight)
    })

    this.delegate = new Cesium.Primitive({
      geometryInstances: new Cesium.GeometryInstance({
        geometry: geometry
      }),
      appearance: new Cesium.MaterialAppearance({
        material: Cesium.Material.fromType('DiffuseWall', {
          color: this._style?.color
        }),
        flat: true
      }),
      asynchronous: false
    })

  }

  /**
   *
   * @param length
   * @param hegiht
   * @returns {*[]}
   * @private
   */
  _getHeights(length, hegiht) {
    let heights = []
    for (let i = 0; i < length; i++) {
      heights.push(hegiht)
    }
    return heights
  }

  /**
   * 设置geometry样式
   * @param {*} style 
   * @returns 
   */
  setStyle(style) {
    if (!style) return
    Object.assign(this._style, { ...style })
  }

  /**
   *
   * @returns {*}
   * @private
   */
  _getPositions() {
    let pnts = []
    let modelMatrix = Cesium.Transforms.eastNorthUpToFixedFrame(
      this._center
    )
    for (let i = 0; i < this._style.slices; i++) {
      let angle = (i / this._style.slices) * Cesium.Math.TWO_PI
      let x = Math.cos(angle)
      let y = Math.sin(angle)
      let point = new Cesium.Cartesian3(
        x * this._currentRadius,
        y * this._currentRadius,
        0.0
      )
      pnts.push(
        Cesium.Matrix4.multiplyByPoint(
          modelMatrix,
          point,
          new Cesium.Cartesian3()
        )
      )
    }
    pnts.push(pnts[0])
    return pnts
  }

  set center(position) {
    this._center = position
    return this
  }

  get center() {
    return this._center
  }

  set radius(radius) {
    this._radius = radius
    return this
  }

  get radius() {
    return this._radius
  }

  set height(height) {
    this._height = height
  }

  get height() {
    return this._height
  }


}
